﻿// the notification service
// ported from apprise-v2
define(["common"], function (app) {
    app.factory('notifyService', ["$window", "$document", function ($window, $document) {
        var mWindow = angular.element($window);

        var localization = {
            Ok: "Ok",
            Cancel: "Cancel",
            Yes: "Yes",
            No: "No",
            DontAsk: "Don't ask this again",
            BeforeUnloadMessage: "An alert requires attention"
        };

        var container = $document.find(".notify-container");
        var $Apprise = angular.element('<div class="apprise">'),
		    $overlay = angular.element('<div class="apprise-overlay">'),
		    $body = $document.find("body"),
		    $cA = null,
		    AppriseQueue = [];

        $body.append($overlay.css('opacity', '.94')).append($Apprise);

        var apprise = function (text, options) {

            // Restrict blank modals
            if (text === undefined || !text) {
                return false;
            }

            // Necessary variables
            var $me = this,
                    $_inner = angular.element('<div class="apprise-inner">'),
                    $_buttons = angular.element('<div class="apprise-buttons">'),
                    $_input = angular.element('<input type="text">'),
                    $_dontAsk = angular.element('<label><input type="checkbox"/>' + localization.DontAsk + '</label>');

            // Default settings (edit these to your liking)
            var settings = {

                animation: 700,	// Animation speed
                buttons: {
                    confirm: {
                        action: function () { $me.dissapear(); }, // Callback function
                        className: null, // Custom class name(s)
                        id: 'confirm', // Element ID
                        text: localization.Ok // Button text
                    }
                },
                input: false, // input dialog
                dontAsk: { // the checkbox to ask the user to not display this dialog again
                    show: false, // set to true to show the checkbox
                    defaultValue: false // the default value of the checkbox (checked or unchecked)
                },
                override: true, // Override browser navigation while Apprise is visible
                action: null, // fires when user action received
                afterInit: null // callback after initializing
            };

            // Merge settings with options
            angular.extend(settings, options);

            // Close current Apprise, exit
            if (text === 'close') {
                $cA.dissapear();
                return;
            }

            // If an Apprise is already open, push it to the queue
            if ($Apprise.is(':visible')) {

                AppriseQueue.push({ text: text, options: settings });

                return;
            }

            // Width adjusting function
            this.adjustWidth = function () {

                var window_width = mWindow.width(), w = "20%", l = "40%";

                if (window_width <= 800) {
                    w = "90%", l = "5%";
                } else if (window_width <= 1400 && window_width > 800) {
                    w = "70%", l = "15%";
                } else if (window_width <= 1800 && window_width > 1400) {
                    w = "50%", l = "25%";
                } else if (window_width <= 2200 && window_width > 1800) {
                    w = "30%", l = "35%";
                }

                $Apprise.css('width', w).css('left', l);

            };

            // Close function
            this.dissapear = function (callback) {

                $Apprise.animate({
                    top: '-100%'
                }, settings.animation, function () {

                    $overlay.fadeOut(300, function () {
                        $Apprise.hide(function () {
                            // Unbind window listeners
                            mWindow.unbind("beforeunload");
                            mWindow.unbind("keydown");

                            // If in queue, run it
                            if (AppriseQueue[0]) {
                                apprise(AppriseQueue[0].text, AppriseQueue[0].options);
                                AppriseQueue.splice(0, 1);
                            }

                            if (callback) callback();
                        });
                    });
                });
                return;
            };

            // Keypress function
            this.keyPress = function () {

                mWindow.bind('keydown', function (e) {
                    // Close if the ESC key is pressed
                    if (e.keyCode === 27) {

                        if (settings.buttons.cancel) {
                            $document.find("#apprise-btn-" + settings.buttons.cancel.id).trigger('click');
                        } else {
                            $me.dissapear(settings.action);
                        }

                        if (settings.action) action();
                    } else if (e.keyCode === 13) {

                        if (settings.buttons.confirm) {
                            $document.find("#apprise-btn-" + settings.buttons.confirm.id).trigger('click');
                        } else {
                            $me.dissapear(settings.action);
                        }
                    }
                });
            };

            $cA = this;

            // Add buttons
            angular.forEach(settings.buttons, function (button, i) {

                if (button) {

                    // Create button
                    var $_button = angular.element('<button id="apprise-btn-' + button.id + '">').append(button.text);

                    // Add custom class names
                    if (button.className) {
                        $_button.addClass(button.className);
                    }

                    // Add to buttons
                    $_buttons.append($_button);

                    // Callback (or close) function
                    $_button.on("click", function () {

                        // Build response object
                        var response = {
                            clicked: button, // Pass back the object of the button that was clicked
                            input: ($_input.val() ? $_input.val() : null), // User inputted text
                            dialog: $cA,
                            dontAsk: settings.dontAsk && settings.dontAsk.show && $_dontAsk.find("input").is(":checked")
                        };

                        button.action(response);

                        if (settings.action) settings.action(response);
                    });
                }
            });

            // Disabled browser actions while open
            if (settings.override) {
                mWindow.on('beforeunload', function (e) {
                    return localization.BeforeUnloadMessage;
                });
            }

            // Adjust dimensions based on window
            $me.adjustWidth();

            mWindow.resize(function () { $me.adjustWidth() });

            // Append elements, show Apprise
            $Apprise.html('').append($_inner.append('<div class="apprise-content">' + text + '</div>')).append($_buttons);

            if (settings.input) {
                if (typeof settings.input === "string") {
                    $_input.val(settings.input);
                }

                $_inner.find('.apprise-content').append($('<div class="apprise-input">').append($_input));
            }

            if (settings.dontAsk && settings.dontAsk.show) {
                $_buttons.prepend($_dontAsk);

                if (settings.dontAsk.defaultValue) {
                    $_dontAsk.find("input[type=checkbox]").prop('checked', true);
                }
            }

            $overlay.fadeIn(300);
            $Apprise.show().animate({
                top: '20%'
            },
                settings.animation,
                function () {
                    $me.keyPress();
                }
            );

            // Focus on input
            if (settings.input) {
                $_input.focus();
            }

            if (settings.afterInit) {
                settings.afterInit(this);
            }
        };

        return {
            setup: function (options) {
                if (!options) return false;

                if (options.localization) localization = angular.extend(localization, options.localization);
            },
            alert: function (message, options) { apprise(message, options); },
            prompt: function () {
                if (arguments.length < 2) return;
                var message = arguments[0];

                var defaultValue = true;
                var callback = arguments[1];
                if (arguments.length > 2) {
                    defaultValue = arguments[1];
                    callback = arguments[2];
                }

                apprise(message, {
                    buttons: {
                        confirm: {
                            action: function (r) { r.dialog.dissapear(); if (callback) callback(r.input); },
                            id: 'yes',
                            text: localization.Ok
                        },
                        cancel: {
                            action: function (r) { r.dialog.dissapear(); if (callback) callback(null); },
                            id: 'no',
                            text: localization.Cancel
                        }
                    },
                    input: defaultValue
                });
            },
            confirm: function (message, callback) {
                apprise(message, {
                    buttons: {
                        confirm: {
                            action: function (r) { r.dialog.dissapear(); if (callback) callback(true); },
                            id: 'yes',
                            text: localization.Yes
                        },
                        cancel: {
                            action: function (r) { r.dialog.dissapear(); if (callback) callback(false); },
                            id: 'no',
                            text: localization.No
                        }
                    }
                });
            },
            message: function (message, timeout, callback) {
                apprise(message, {
                    buttons: {},
                    afterInit: function ($this) {
                        setTimeout(function () { $this.dissapear(callback); }, timeout ? timeout : 2000);
                    },
                    action: callback
                });
            }
        };
    }]);

    app.directive("editPrompt", ["notifyService", "$compile", '$parse', function (notifyService, $compile, $parse) {
        return {
            restrict: "AE",
            scope: {
                label: '=label',
                model: '=model'
            },
            replace: true,
            template: "<span style='cursor: pointer;'></span>",
            link: function (scope, element, attrs) {
                var label = scope.label ? scope.label : " ";

                var spanText = angular.element("<span></span>")
                    .html(scope.model);
                element.append(spanText)
                    .append(" <i class='glyphicon glyphicon-edit'></i>");

                scope.$watch("model", function (value) {
                    spanText.html(value);
                });
                element.bind("click", function () {
                    notifyService.prompt(label, scope.model, function (newValue) {
                        if (!newValue) return;
                        scope.model = newValue;
                        scope.$apply();
                    });
                });                
            }
        };
    }]);
    return null;
});